﻿using System;
using OpenTK;
using System.Linq;

namespace Mono.Rift.Core.Graphics
{
	public class ShaderSet

	{
		public Shader[] Shaders { get; set; }
		public int ProjLoc { get; set; }
		public int ViewLoc { get; set; }
		public bool UsesLighting { get; set; }
		public int LightingVer { get; set; }

		public ShaderSet ()
		{
			Shaders = new Shader[(int)ShaderStage.Count];
		}

		public virtual void set(PrimitiveTypes prim)
		{

			for (var i = 0; i < (int)ShaderStage.Count; i++) {
				if (Shaders [i] != null)
					Shaders [i].set (prim);
			}
		}

		public virtual void setShader(Shader s)
		{
			Shaders [(int)s.Stage] = s;
		}

		public virtual void unsetShader(int stage)
		{
			Shaders [stage] = null;
		}

		public virtual bool setUniform(string name, int n, float[] v)
		{
			bool result = false;
			for (var i = 0; i < (int)ShaderStage.Count; i++) {
				if (Shaders[i] != null) result |= Shaders[i].setUniform(name, n, v);
			}
			return result;
		}

		public bool setUniform1f(string name, float x)
		{
			return setUniform(name, 1, new [] { x });
		}

		public bool setUniform2f(string name, float x, float y)
		{
			return setUniform(name, 2, new [] { x, y });
		}

		public bool setUniform4f(string name, float x, float y, float z, float w = 1)
		{
			return setUniform(name, 4, new [] { x, y, z, w });
		}

		public bool setUniformv(string name, int n, Vector3 v)
		{
			return setUniform (name, 4, new [] { v.X, v.Y, v.Z, 1 });
		}

		public bool setUniform4fv(string name, int n, Vector4[] v)
		{
			return setUniform (name, 4 * n, v.SelectMany (cv => new [] { cv.X, cv.Y, cv.Z, cv.W }).ToArray ());
		}

		public bool setUniform4x4f(string name, int n, Matrix4 m)
		{
			return setUniform (name, 16, new [] {
				m.M11,
				m.M12,
				m.M13,
				m.M14,
				m.M21,
				m.M22,
				m.M23,
				m.M24,
				m.M31,
				m.M32,
				m.M33,
				m.M34,
				m.M41,
				m.M42,
				m.M43,
				m.M44
			});
		}
	}
}

